#include "StdAfx.h"
#include "StateMain.h"
#include "ResourceManager.h"

StateMain::StateMain (int numCol, int numRow): 
m_iCol(numCol), 
m_iRow(numRow),
m_bIsClearing(false),
m_flyer(NULL),
m_camera(),
m_genPos()
{
	m_grid = new int*[numCol];
	for (int col=0; col<numCol; col++)
	{
		m_grid[col] = new int[numRow];
		for (int row=0; row<numRow; row++)
		{
			m_grid[col][row] = 0;
		}
	}
	m_iNext = GetResourceManager()->GetRandomPrefab();
	m_camera.Init();
}

StateMain::~StateMain ()
{
	for (int i=0; i<m_iCol; i++)
	{
		delete[] m_grid[i];
	}
	delete[] m_grid;
	delete m_flyer;
	
	for (std::vector<Object*>::iterator it=m_object.begin(); it!=m_object.end();)
	{
		delete *it;
		it = m_object.erase(it);
	}
}

// Collision Detector
Vector2Int & StateMain::ConvertToWorldPos (Vector2Int & position)
{
	if (position.x < 0) position.x += m_iCol;
	else if (position.x >= m_iCol) position.x -= m_iCol;

	return position;
}

bool StateMain::IsAvailableSpace (std::vector<Vector2Int> block, Vector2Int position)
{
	for (int i=0; i<block.size(); i++)
	{
		Vector2Int vector = ConvertToWorldPos(block[i] + position);
		if (vector.y < m_iRow)
		{
			if ( m_grid[vector.x][vector.y] != 0 ) return false;
		}
		else
		{
			return false;
		}
	}
	return true;
}

void StateMain::UpdateGrid (Object* object)
{
	std::vector<Vector2Int> block = object->GetBlock();
	Vector2Int position = object->GetPosition();

	for (std::vector<Vector2Int>::iterator it=block.begin(); it!=block.end(); it++)
	{
		Vector2Int vector = ConvertToWorldPos( (*it) + position );
		m_grid[vector.x][vector.y] = 1;
	}
}
// end collision detector

void StateMain::Update (float deltaTime)
{
	if (m_bIsClearing)
	{
		//To do: What do we want to do when clearing???
		ClearRows();
		m_bIsClearing = false;
		return;
	}
	else if (m_flyer == NULL)
	{
		GenBlock();
		return;
	}

	if (m_flyer) 
	{
		static float wait = 0;
		if ( m_flyer->Update(deltaTime) )
		{
			wait = 0;
			m_bIsClearing = false;
		}
		else
		{
			// Give the user a certain amount of time before it's too late
			wait += deltaTime;
			if (wait >= 0.05f)
			{
				m_object.push_back(m_flyer);
				UpdateGrid(m_flyer);
				m_flyer = NULL;

				CheckIfAnyRowToClear();
				if (m_rowToClear.size())
				{
					m_bIsClearing = true;
				}
			}
		}
	}
	for (std::vector<Object*>::iterator it=m_object.begin(); it!=m_object.end(); it++)
	{
		if ( !(*it)->Update(deltaTime) )
			UpdateGrid( (*it) );
	}
}

void StateMain::GenBlock ()
{
	Prefab* prefab = GetResourceManager()->GetPrefab(m_iNext);
	if ( !IsAvailableSpace(prefab->m_block, Vector2Int()) ) 
	{
		//To do: Game over here
		return;
	}

	m_iNext = GetResourceManager()->GetRandomPrefab();
	m_flyer = new Object(prefab, m_genPos, 10.0f, this);
}

void StateMain::CheckIfAnyRowToClear ()
{
	for (int row=m_iRow-1; row>=0; row--)
	{
		bool shouldClear = true;
		for (int col=0; col<m_iCol; col++)
		{
			if (m_grid[col][row] == 0)
			{
				shouldClear = false;
				break;
			}
		}

		if (shouldClear)
		{
			m_rowToClear.push_back(row);
		}
	}
}

void StateMain::ClearRows ()
{
	if (m_rowToClear.empty()) return;

	for (int row=0; row<m_iRow; row++)
		for (int col=0; col<m_iCol; col++)
		{
			m_grid[col][row] = 0;
		}

	std::vector<Object*> newObjectList;
	for (std::vector<Object*>::iterator it=m_object.begin(); it!=m_object.end(); )
	{
		std::vector<Object*> newObjects;
		if ( (*it)->SplitObject(newObjects) )
		{
			delete (*it);
		}
		it = m_object.erase(it);
		
		for (std::vector<Object*>::iterator it_obj=newObjects.begin(); it_obj!=newObjects.end(); it_obj++)
		{
			newObjectList.push_back(*it_obj);
		}
	}

	for (std::vector<Object*>::iterator it=newObjectList.begin(); it!=newObjectList.end(); it++)
	{
		m_object.push_back(*it);
	}

	m_rowToClear.clear();
}

std::vector<int> StateMain::GetRowToClear ()
{
	return m_rowToClear;
}

void StateMain::Render ()
{
	for (std::vector<Object*>::iterator it=m_object.begin(); it!=m_object.end(); it++)
	{
		(*it)->Render();
	}
	if (m_flyer)
	{
		m_flyer->Render();
	}
}

// Input handler
bool StateMain::OnKeyUp (int keycode)
{
	if (keycode == KEY_DOWN)
	{
		if (m_flyer)
			m_flyer->DropFast(false);
		return true;
	}
	return false;
}

bool StateMain::OnKeyDown (int keycode)
{
	switch (keycode)
	{
	case KEY_LEFT:
		{
			m_genPos.x++;
			m_genPos = ConvertToWorldPos(m_genPos);

			if (m_flyer) m_flyer->Move ( Vector2Int( 1, 0) );

			m_camera.Move ( -2.0f * PI / m_iCol );
			return true;
		}
	case KEY_RIGHT:
		{
			m_genPos.x--;
			m_genPos = ConvertToWorldPos(m_genPos);

			if (m_flyer) m_flyer->Move ( Vector2Int( -1, 0) );

			m_camera.Move ( 2.0f * PI / m_iCol );
			return true;
		}
	case KEY_DOWN:
		{
			if (m_flyer) m_flyer->DropFast(true);
			return true;
		}
	case KEY_SPACE:
		{
			if (m_flyer) m_flyer->Rotate();
			return true;
		}
	default: return false;
	}
}

Camera* StateMain::GetCamera ()
{
	return &m_camera;
}